Broadly speaking, there are two approaches to implementing attribute grammars:
Topological Sort
A tool is used to analyze the definition of attributes and determine an evaluation order for them. This can be done by doing a topological sort on the attribute definitions with dependencies between them as the ordering. This order can then be baked into an implementation (e.g., through code generation). However, it is not always so straightforward. Evaluating an attribute grammar may require multiple passes over the tree or an arbitrary, source-dependent number of passes up and down the tree. It is my understanding that this has been the subject of academic research, but I am not familiar with any of the literature.
Lazy Evaluation
Each attribute is evaluated lazily on demand, and the result may or may not be cached. If a cycle is encountered at runtime, different strategies may be employed. Some tools fail to terminate (e.g. Happy "you can write an attribute grammar which fails to terminate. This generally happens when semantic rules are written which cause a circular dependency on the value of an attribute."). Other tools will detect the cycle and throw an exception. Some tools support calculating the fixed point if specifically requested (e.g. JastAdd Circular Attributes "The evaluation stops when the value equals that for the previous iteration."). Lazy evaluation seems to be the approach most modern tools use.
You could look at some of the attribute grammar tools for more details. I am aware of JastAdd (Lazy, Java), Happy (Lazy, Haskell), and Silver (Lazy, Java).